﻿using CaseManagerLibrary.Log;
using CaseManagerLibrary.Models;
using NetSDKCS;
using PSDLib.Models;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PSDLib.Download
{
    public class HK_NVR_Downloader : IDownloader
    {
        public int m_LoginID { get; set; } = -1;
        private int m_DownloadID { get; set; } = -1;
        public string Id { get; set; }
        public dl_files FileInfo { get; set; }
        public ILog Logger { get; set; }

        public IDownloadServer DownloadServer { get; set; }
        public ConsoleProgressBar ProgressBar { get; set; }

        private System.Timers.Timer progressTimer;

        public event UpdateDownloadProgressEventHandler UpdateDownloadProgress;
        public event FileDownloadCompletedEventHandler FileDownloadSuccess;
        public event FileDownloadCompletedEventHandler FileDownloadFail;
        public event ResetSessionEventHandler ResetSession;

        public HK_NVR_Downloader()
        {
            progressTimer = new System.Timers.Timer();
            progressTimer.Interval = 1000;
            progressTimer.Enabled = false;
            progressTimer.Elapsed += ProgressTimer_Elapsed;
        }

        public HResult Download(dl_files file)
        {
            HResult result = new HResult() { success = false };

            FileInfo = file;
            FileInfo.dl_progress = 0;

            try
            {
                DateTime startTime = file.video_start_time;
                DateTime endTime = file.video_end_time;

                if (file.video_end_time == file.video_start_time)
                {
                    result.message = "The start time is the same ad the end time(开始时间与结束时间相同)!";
                    FileInfo.error_log = result.message;
                    FinishDownload(false);
                    return result;
                }
                if (file.video_start_time > file.video_end_time)
                {
                    result.message = "The start time is greater than the end time(开始时间大于结束时间)!";
                    FileInfo.error_log = result.message;
                    FinishDownload(false);
                    return result;
                }

                HKNetSDK.NET_DVR_PLAYCOND struDownPara = new HKNetSDK.NET_DVR_PLAYCOND();
                struDownPara.dwChannel = Convert.ToUInt32(file.channel_id); //通道号 Channel number  

                //设置下载的开始时间 Set the starting time
                struDownPara.struStartTime.dwYear = (uint)file.video_start_time.Year;
                struDownPara.struStartTime.dwMonth = (uint)file.video_start_time.Month;
                struDownPara.struStartTime.dwDay = (uint)file.video_start_time.Day;
                struDownPara.struStartTime.dwHour = (uint)file.video_start_time.Hour;
                struDownPara.struStartTime.dwMinute = (uint)file.video_start_time.Minute;
                struDownPara.struStartTime.dwSecond = (uint)file.video_start_time.Second;

                //设置下载的结束时间 Set the stopping time
                struDownPara.struStopTime.dwYear = (uint)file.video_end_time.Year;
                struDownPara.struStopTime.dwMonth = (uint)file.video_end_time.Month;
                struDownPara.struStopTime.dwDay = (uint)file.video_end_time.Day;
                struDownPara.struStopTime.dwHour = (uint)file.video_end_time.Hour;
                struDownPara.struStopTime.dwMinute = (uint)file.video_end_time.Minute;
                struDownPara.struStopTime.dwSecond = (uint)file.video_end_time.Second;

                if (!Directory.Exists(file.file_path))
                {
                    Directory.CreateDirectory(file.file_path);
                }

                string fileName = Path.Combine(file.file_path, file.file_name);

                System.IO.File.Delete(fileName);

                m_DownloadID = HKNetSDK.NET_DVR_GetFileByTime_V40(m_LoginID, fileName, ref struDownPara);

                if (m_DownloadID < 0)
                {
                    result.success = false;
                    uint code = HKNetSDK.NET_DVR_GetLastError();
                    result.message = "NET_DVR_GetFileByTime_V40 failed, error code = " + code;
                    FileInfo.error_log = (code == 7 ? "获取连接Session信息" : result.message);
                    FileInfo.state = 2;
                    FinishDownload(false);
                }
                else
                {
                    uint iOutValue = 0;
                    if (HKNetSDK.NET_DVR_PlayBackControl_V40(m_DownloadID, HKNetSDK.NET_DVR_PLAYSTART, IntPtr.Zero, 0, IntPtr.Zero, ref iOutValue))
                    {
                        result.success = true;
                        progressTimer.Enabled = true;
                    }
                    else
                    {
                        result.success = false;
                        uint code = HKNetSDK.NET_DVR_GetLastError();
                        result.message = "NET_DVR_PLAYSTART failed, error code= " + code;
                        FileInfo.error_log = (code == 7 ? "获取连接Session信息" : result.message);
                        FileInfo.state = 2;
                        FinishDownload(false);
                    }
                }
            }
            catch (Exception ex)
            {
                result.success = false;
                result.message = ex.Message;
                FileInfo.error_log = result.message;
                FileInfo.state = 2;
                FinishDownload(false);
            }

            return result;
        }

        private void ProgressTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            try
            {
                if (m_DownloadID >= 0)
                {
                    int iPos = HKNetSDK.NET_DVR_GetDownloadPos(m_DownloadID);

                    FileInfo fi = new FileInfo(Path.Combine(FileInfo.file_path, FileInfo.file_name));
                    
                    FileInfo.file_size = fi.Length;

                    if (iPos < 100)
                    {
                        int diff = Convert.ToInt32((DateTime.Now - FileInfo.dl_start_time.Value).TotalSeconds);

                        if (diff > 0)
                        {
                            FileInfo.dl_speed = FileInfo.file_size / diff;
                        }
                        FileInfo.dl_progress = iPos;

                        UpdateDownloadProgress?.Invoke(this, FileInfo, diff);
                    }
                    else
                    {
                        FileInfo.dl_progress = 100;
                        FinishDownload(true);
                    }
                }
            }
            catch (Exception ex)
            { }
        }

        public void FinishDownload(bool success)
        {
            progressTimer.Enabled = false;
            FileInfo.dl_end_time = DateTime.Now;
            FileInfo.state = (success ? 1 : 2);

            System.Threading.Thread.Sleep(1000 * 2);

            //Logout();

            if (success)
            {
                FileDownloadSuccess(this, FileInfo);
            }
            else
            {
                FileDownloadFail(this, FileInfo);
            }
        }

        public void ResetSessionInfo(params object[] args)
        {
            if (args.Length == 1)
            {
                m_LoginID = (int)args[0];
            }
        }

        public HResult Stop()
        {
            HResult result = new HResult();

            try
            {
                result.success = HKNetSDK.NET_DVR_StopGetFile(m_DownloadID);

                if (!result.success)
                {
                    result.message = "NET_DVR_StopGetFile failed, error code= " + HKNetSDK.NET_DVR_GetLastError();

                    Logger.Error("停止下载文件失败：" + (FileInfo == null ? "" : FileInfo.file_name) + " - " + result.message);
                }
                else
                {
                    Logger.Log("停止下载文件：" + (FileInfo == null ? "" : FileInfo.file_name));
                }
            }
            catch (Exception ex)
            {
                result.success = false;
                result.message = ex.Message;
            }

            return result;
        }
    }
}
